
`include "common_header.verilog"

//  *************************************************************************
//  File : align_sync20b.v
//  *************************************************************************
//  This program is controlled by a written license agreement.
//  Unauthorized reproduction or use is expressly prohibited. 
//  Copyright (c) 2003-2005 Morethanip
//  An der Steinernen Brueke 1, 85757 Karlsfeld, Germany
//  info@morethanip.com
//  http://www.morethanip.com
//  *************************************************************************
//  Designed by : Sebastien Marcellier
//  info@morethanip.com
//  *************************************************************************
//  Description: Code-group Alignment 
//               The code group aligment is realized on Comma+ and Comma-
//               Detection
//  Version    : $Id: align_sync20b.v,v 1.1 2011/03/29 10:36:57 mr Exp $
//  *************************************************************************

module align_sync20b (

   rst_align,
   din,
   dout,
   sync,
   comma,
   ce,
   clk,
  `ifdef USE_CLK_ENA
   clk_ena,
  `endif
   enable_cgalign,
   rst);
   
`include "mtip_xgxs_package.verilog"
   
input   rst_align;      //  Reset Alignment        
input   [19:0] din;     //  Parallel byte of incoming data
output  [19:0] dout;    //  Parallel output data                 
output  sync;           //  Asserted when synchronisation detected
output  comma;          //  Comma Detect        
input   ce;             //  Clock enable                 
input   clk;            //  Main Clock
`ifdef USE_CLK_ENA
input   clk_ena;        //  Enable clk
`endif
input   enable_cgalign; //  Code groip alignment
input   rst;            //  Asynchronour reset

wire    [19:0] dout; 
reg     sync; 
reg     comma;

parameter COMMAP = 7'b 1111100;   
parameter COMMAN = 7'b 0000011;   

reg     [19:0] dout_int;
reg     cgalign_reg;

`ifdef ENA_CG_ALIGNMENT

   reg     [19:0] din_reg; 
   reg     [19:0] din_reg2; 
   wire    [29:0] par; 
   wire    [28:0] pars; 
   reg     [28:0] par_r; 
   wire    [3:0] sel;           // step2: selection suggestion (combinatorial)
   reg     [3:0] align_det;     // final data mux control
   reg     [3:0] align_det_d;   // final data mux control
   wire    [3:0] sel0;
   wire    [3:0] sel1;
   wire    [3:0] sel2;
   wire    [3:0] sel3;
   wire    [3:0] sel4;
   wire    [3:0] sel5;
   wire    [3:0] sel6;
   wire    [3:0] sel7;
   wire    [3:0] sel8;
   wire    [3:0] sel9;

   `ifdef MTIPXGXS_IREGS
  
   always @(posedge clk or posedge rst)
      begin : process_1a
      if (rst == 1'b 1)
         begin
         din_reg  <= {20{1'b 0}};   
         end
      else
         begin
         
         `ifdef USE_CLK_ENA
            if(clk_ena == 1'b 1)
            begin
         `endif          
         
                 if (ce == 1'b 1)
                    begin
                    din_reg  <= din;   
                    end
         
         `ifdef USE_CLK_ENA
            end
         `endif         
         
         end
      end
   `else
  
   always @(din)
   begin
        din_reg  = din;   
   end        
   
   `endif
   
   always @(posedge clk or posedge rst)
      begin : process_1b
      if (rst == 1'b 1)
         begin
         din_reg2 <= {20{1'b 0}};   
         end
      else
         begin
         
         `ifdef USE_CLK_ENA
            if(clk_ena == 1'b 1)
            begin
         `endif          
         
                 if (ce == 1'b 1)
                    begin
                    din_reg2 <= din_reg;   
                    end
         
         `ifdef USE_CLK_ENA
            end
         `endif         
         
         end
      end

   assign pars = {din_reg[8:0], din_reg2}; 


   // Search Comma+/-
   // ---------------

        assign par = {din_reg[19:0], din_reg2[19:10]}; 

        
        assign sel0 = ((par[26:20] == COMMAP) | (par[26:20] == COMMAN) | (par[16:10] == COMMAP) | (par[16:10] == COMMAN )) ? 4'b 0001 : 4'b 0000;
        assign sel1 = ((par[27:21] == COMMAP ) | (par[27:21] == COMMAN) | (par[17:11] == COMMAP) | (par[17:11] == COMMAN )) ? 4'b 0010 : 4'b 0000;
        assign sel2 = ((par[28:22] == COMMAP ) | (par[28:22] == COMMAN) | (par[18:12] == COMMAP) | (par[18:12] == COMMAN )) ? 4'b 0011 : 4'b 0000;
        assign sel3 = ((par[29:23] == COMMAP ) | (par[29:23] == COMMAN) | (par[19:13] == COMMAP) | (par[19:13] == COMMAN )) ? 4'b 0100 : 4'b 0000;
        assign sel4 = ((par[10:4] == COMMAP ) | (par[10:4] == COMMAN) | (par[20:14] == COMMAP) | (par[20:14] == COMMAN)) ? 4'b 0101 : 4'b 0000;
        assign sel5 = ((par[11:5] == COMMAP ) | (par[11:5] == COMMAN) | (par[21:15] == COMMAP) | (par[21:15] == COMMAN)) ? 4'b 0110 : 4'b 0000;
        assign sel6 = ((par[12:6] == COMMAP ) | (par[12:6] == COMMAN) | (par[22:16] == COMMAP) | (par[22:16] == COMMAN)) ? 4'b 0111 : 4'b 0000;
        assign sel7 = ((par[13:7] == COMMAP ) | (par[13:7] == COMMAN) | (par[23:17] == COMMAP) | (par[23:17] == COMMAN)) ? 4'b 1000 : 4'b 0000;
        assign sel8 = ((par[14:8] == COMMAP ) | (par[14:8] == COMMAN) | (par[24:18] == COMMAP) | (par[24:18] == COMMAN)) ? 4'b 1001 : 4'b 0000;
        assign sel9 = ((par[15:9] == COMMAP ) | (par[15:9] == COMMAN) | (par[25:19] == COMMAP) | (par[25:19] == COMMAN)) ? 4'b 1010 : 4'b 0000;

        assign sel = sel0 | sel1 | sel2 | sel3 | sel4 | sel5 | sel6 | sel7 | sel8 | sel9;

   // Memorize Shift
   // --------------
        
   always @(posedge clk or posedge rst)
      begin : p_p
      if (rst == 1'b 1)
         begin
         align_det <= 4'b 0000;   
         end
      else
         begin
         
         `ifdef USE_CLK_ENA
            if(clk_ena == 1'b 1)
            begin
         `endif          
         
                 if (ce == 1'b 1 & enable_cgalign == 1'b 1 & sel != 4'b 0000)
                    begin
        
                        align_det <= sel;
                        
                    end
      
         `ifdef USE_CLK_ENA
            end
         `endif      
      
      end
   end

   always @(posedge rst or posedge clk)
      begin : process_3
      if (rst == 1'b 1)
         begin
         par_r    <= {29{1'b 0}};
         dout_int <= {20{1'b 0}};
         end
      else
         begin
         
         `ifdef USE_CLK_ENA
            if(clk_ena == 1'b 1)
            begin
         `endif          
         
         if (ce == 1'b 1)
            begin
                
            par_r <= pars[28:0];
                
            case( align_det )
                4'b 0001:
               begin
               dout_int <= par_r[19:0];   
               end
                4'b 0010:
               begin
               dout_int <= par_r[20:1];   
               end
                4'b 0011:
               begin
               dout_int <= par_r[21:2];   
               end
                4'b 0100:
               begin
               dout_int <= par_r[22:3];   
               end
                4'b 0101:
               begin
               dout_int <= par_r[23:4];   
               end
                4'b 0110:
               begin
               dout_int <= par_r[24:5];   
               end
                4'b 0111:
               begin
               dout_int <= par_r[25:6];   
               end
                4'b 1000:
               begin
               dout_int <= par_r[26:7];   
               end
                4'b 1001:
               begin
               dout_int <= par_r[27:8];   
               end
                4'b 1010:
               begin
               dout_int <= par_r[28:9];   
               end
                default:
               begin
               dout_int <= {20{1'b 0}};   
               end     
            endcase
            end
         
         `ifdef USE_CLK_ENA
            end
         `endif         
         
         end
      end
      
   always @(posedge clk or posedge rst)
      begin : p3
      if (rst == 1'b 1)
         begin
         align_det_d <= 4'b 0000;   
         end
      else
         begin
         
         `ifdef USE_CLK_ENA
            if(clk_ena == 1'b 1)
            begin
         `endif          
         
         if (ce == 1'b 1)
            begin
                
                align_det_d <= align_det;
                
            end
        
         `ifdef USE_CLK_ENA
            end
         `endif        
        
        end
      end

   always @(posedge clk or posedge rst)
      begin : process_4
      if (rst == 1'b 1)
         begin
         sync <= 1'b 0;   
         end
      else
         begin
         
         `ifdef USE_CLK_ENA
            if(clk_ena == 1'b 1)
            begin
         `endif          
         
         if ((enable_cgalign==1'b1 & cgalign_reg==1'b0) |
             (align_det != align_det_d) |
             (rst_align == 1'b 1))
            begin
            sync <= 1'b 0;   
            end       
         else
            begin
            sync <= 1'b 1;   
            end
         
         `ifdef USE_CLK_ENA
            end
         `endif         
         
         end
      end
      
`else

   `ifdef MTIPXGXS_IREGS
   
   always @(posedge rst or posedge clk)
      begin
         if (rst == 1'b 1)
            begin
            dout_int <= 20'h0 ;	
            end
         else
            begin
            
         `ifdef USE_CLK_ENA
            if(clk_ena == 1'b 1)
            begin
         `endif             
            
                dout_int <= din ;
            
         `ifdef USE_CLK_ENA
            end
         `endif            
            
            end
      end
   
   `else
   always @(din)
      begin
        dout_int = din ;
      end   
   
   `endif
   
   
      
   always @(posedge clk or posedge rst)
      begin : process_4
      if (rst == 1'b 1)
         begin
         sync <= 1'b 0;   
         end
      else
         begin
         
         `ifdef USE_CLK_ENA
            if(clk_ena == 1'b 1)
            begin
         `endif         
         
         if ((enable_cgalign==1'b1 & cgalign_reg==1'b0) |
             (rst_align == 1'b 1))
            begin
            sync <= 1'b 0;   
            end
         else
            begin
            sync <= 1'b 1;   
            end
         
         `ifdef USE_CLK_ENA
            end
         `endif         
         
         end
      end      

`endif

assign dout = dout_int; 

always @(posedge rst or posedge clk)
   begin
      if (rst == 1'b 1)
         begin
         cgalign_reg   <= 1'b 0;	
         end
      else
         begin
         
         `ifdef USE_CLK_ENA
            if(clk_ena == 1'b 1)
            begin
         `endif         
         
                cgalign_reg   <= enable_cgalign ;
         
         `ifdef USE_CLK_ENA
            end
         `endif         
         
         end
   end

always @(posedge clk or posedge rst)
   begin : process_5
   if (rst == 1'b 1)
      begin
      comma <= 1'b 0;   
      end
   else
      begin
      
         `ifdef USE_CLK_ENA
            if(clk_ena == 1'b 1)
            begin
         `endif      
      
      if (ce == 1'b 1 )
         begin
         if (dout_int[6:0] == COMMAP | dout_int[16:10] == COMMAP |
             dout_int[6:0] == COMMAN | dout_int[16:10] == COMMAN )
            begin
            comma <= 1'b 1;   
            end
         else
            begin
            comma <= 1'b 0;   
            end
         end
      
         `ifdef USE_CLK_ENA
            end
         `endif      
      
      end
   end
   
endmodule // module align_sync20b
